<?php
namespace apps\common\controllers;
if( ! APP_ROOT  ) return 'Direct Access Deny!';

return;

use Phalcon\Mvc\Controller;
use libraries\DLock;
use enums\RetCodeEnums;

/**
 * 
 * 由于性能等原因暂时不对外提供服务
 * 
 * @author fzq
 * @comment( comment = '因此服务都是一些简单参数的服务故完全使用了get请求，而未使用rest来实现' )
 * 
 * version 0.0.1 未实现权限验证
 */
class DlockController extends Controller
{
	use JsonRet;
	
	const DEFAULT_SIZE = 20;

	const DEFAULT_HOLD_SECONDS = 100;
	
	/**
	 * 强制初始化（强制覆盖原有值，自行处理善后）
	 */
	const INIT_FORCE = 1;
	
	/**
	 * 非强制初始化 （有则返回剩余资源量，无则直接初始化）
	 */
	const INIT_FORCE_NONE = 2;
	
	private $_dLock = null;
	
	public function initialize()
	{
		$this->_dLock = DLock::getInstance( $this->di );
	}


	/**
	 * 初始化分布式锁
	 *
	 * @param int $iBase
	 * 
	 */
	public function initLockAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iBase = $this->dispatcher->getParam( 'base', 'int' );
		if( !$iBase )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NUM_MSG, RetCodeEnums::ERR_RES_LOCK_NUM );
		}
		
		$iForce = $this->dispatcher->getParam( 'force', 'int' );
		if( $iForce == self::INIT_FORCE )
		{//这里为了安全起见故意留空
			;
		}
		else
		{
			$iForce = self::INIT_FORCE_NONE; 
		}
		
		$iRet = $this->_dLock->initLock( $strLockName, $iResID, $iBase, $iForce );
		if( $iRet >= DLock::ERR_SUCCESS )
		{
			return $this->getRet( $iRet, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
		}
		
		return $this->getRet( null, RetCodeEnums::ERR_PARAMS_MSG, RetCodeEnums::ERR_PARAMS );
	}
	
	
	/**
	 * 锁定指定数量的资源
	 */
	public function lockResAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iApplicantID = $this->dispatcher->getParam( 'aid', 'int' );
		if( !$iApplicantID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iRequestNum = $this->dispatcher->getParam( 'rnum', 'int' );
		if( !$iRequestNum )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iHoldSeconds = $this->dispatcher->getParam( 'seconds', 'int' );
		if( !$iHoldSeconds )
		{
			$iHoldSeconds = self::DEFAULT_HOLD_SECONDS;
		}
		
 		$iRet = $this->_dLock->lockRes( $strLockName, $iResID, $iApplicantID, $iRequestNum, $iHoldSeconds );

 		switch( $iRet )
 		{
 			case DLock::ERR_SUCCESS:
 				return $this->getRet( null, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
 			case DLock::ERR_PARAMETERS:
 				return $this->getRet( null, RetCodeEnums::ERR_PARAMS_MSG, RetCodeEnums::ERR_PARAMS );
 			case DLock::ERR_NONE_INIT:
 				return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NONE_INIT_MSG, RetCodeEnums::ERR_RES_LOCK_NONE_INIT );
 			case DLock::ERR_EXCEED:
 				return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_EXCEED_MSG, RetCodeEnums::ERR_RES_LOCK_EXCEED );
 			case DLock::ERR_INSUFFICIENT:
 				return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_INSUFFICIENT_MSG, RetCodeEnums::ERR_RES_LOCK_INSUFFICIENT );
 			default:
 				return $this->getRet( null, RetCodeEnums::ERR_OTHERS_MSG, RetCodeEnums::ERR_OTHERS );
 		}

	}

	/**
	 * 消费资源
	 */
	public function consumeAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iApplicantID = $this->dispatcher->getParam( 'aid', 'int' );
		if( !$iApplicantID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iRet = $this->_dLock->consume($strLockName, $iResID, $iApplicantID);
		
		if( $iRet >= DLock::ERR_SUCCESS )
		{
			return $this->getRet( $iRet, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
		}
		
		switch( $iRet )
		{
			case DLock::ERR_CONSUME:
				return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_CONSUME_MSG, RetCodeEnums::ERR_RES_LOCK_CONSUME );
			case DLock::ERR_PARAMETERS:
				return $this->getRet( null, RetCodeEnums::ERR_PARAMS_MSG, RetCodeEnums::ERR_PARAMS );
			default:
				return $this->getRet( null, RetCodeEnums::ERR_OTHERS_MSG, RetCodeEnums::ERR_OTHERS );
		}
	}
	
	/**
	 * 删除资源锁
	 * 
	 * 当规格或产品已经下架时
	 */
	public function delLockAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iRet = $this->_dLock->delLock( $strLockName, $iResID );
		switch( $iRet )
		{
			case DLock::ERR_SUCCESS:
				return $this->getRet( null, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
			case DLock::ERR_PARAMETERS:
				return $this->getRet( null, RetCodeEnums::ERR_PARAMS_MSG, RetCodeEnums::ERR_PARAMS );
			default:
				return $this->getRet( null, RetCodeEnums::ERR_OTHERS_MSG, RetCodeEnums::ERR_OTHERS );
		}
	}
	
	/**
	 * 取申请者的资源占用情况
	 */
	public function getApplicantsAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$ret = $this->_dLock->getApplicants( $strLockName, $iResID );
		
		if( is_object( $ret ) )
		{
			return $this->getRet( $ret, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
		}
		
		switch( $ret )
		{
			case DLock::ERR_NO_APPLICANTS:
				return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NO_APPLICANTS_MSG, RetCodeEnums::ERR_RES_LOCK_NO_APPLICANTS );
			case DLock::ERR_PARAMETERS:
				return $this->getRet( null, RetCodeEnums::ERR_PARAMS_MSG, RetCodeEnums::ERR_PARAMS );
			default:
				return $this->getRet( null, RetCodeEnums::ERR_OTHERS_MSG, RetCodeEnums::ERR_OTHERS );
		}
		
	}
	
	/**
	 * 取未锁定的资源
	 */
	public function getNoneLockedResAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$ret = $this->_dLock->getNoneLockedRes( $strLockName, $iResID );
		if( is_object( $ret ))
		{
			return $this->getRet( $ret, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
		}
		
		switch( $ret )
		{
			case DLock::ERR_PARAMETERS:
				return $this->getRet( null, RetCodeEnums::ERR_PARAMS_MSG, RetCodeEnums::ERR_PARAMS );
			case DLock::ERR_NONE_INIT:
				return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NONE_INIT_MSG, RetCodeEnums::ERR_RES_LOCK_NONE_INIT );
			default:
				return $this->getRet( null, RetCodeEnums::ERR_OTHERS_MSG, RetCodeEnums::ERR_OTHERS );
		}
		
	}
	
	/**
	 * 取初始化时分配的资源
	 */
	public function getResInitCntAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iRet = $this->_dLock->getResInitCnt( $strLockName, $iResID );
		if( $iRet >= DLock::ERR_SUCCESS )
		{
			return $this->getRet( $iRet, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
		}
		
		return $this->getRet( null, RetCodeEnums::ERR_OTHERS_MSG, RetCodeEnums::ERR_OTHERS );
	}
	
	/**
	 * 取未消费的资源量
	 */
	public function getResLeftCntAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iRet = $this->_dLock->getResLeftCnt( $strLockName, $iResID );
		if( $iRet >= DLock::ERR_SUCCESS )
		{
			return $this->getRet( $iRet, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
		}
		
		if( DLock::ERR_PARAMETERS == $iRet )
		{
			return $this->getRet( null, RetCodeEnums::ERR_PARAMS_MSG, RetCodeEnums::ERR_PARAMS );
		}
		
		return $this->getRet( null, RetCodeEnums::ERR_OTHERS_MSG, RetCodeEnums::ERR_OTHERS );
		
	}
	
	/**
	 * 取资源情况
	 */
	public function getResStatusAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$ret = $this->_dLock->getResStatus( $strLockName, $iResID );
		if( is_array( $ret ) )
		{
			return $this->getRet( $ret, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
		}
		
		switch( $ret )
		{
			case DLock::ERR_PARAMETERS:
				return $this->getRet( null, RetCodeEnums::ERR_PARAMS_MSG, RetCodeEnums::ERR_PARAMS );
			case DLock::ERR_NONE_INIT:
				return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NONE_INIT_MSG, RetCodeEnums::ERR_RES_LOCK_NONE_INIT );
			default:
				return $this->getRet( null, RetCodeEnums::ERR_OTHERS_MSG, RetCodeEnums::ERR_OTHERS );
		}
	}
	
	/**
	 * 解锁
	 */
	public function unlockResAction()
	{
		$strLockName = $this->dispatcher->getParam( 'lname', 'trim' );
		if( !$strLockName )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_NAME_MSG, RetCodeEnums::ERR_RES_LOCK_NAME );
		}
		
		$iResID = $this->dispatcher->getParam( 'rid', 'int' );
		if( !$iResID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iApplicantID = $this->dispatcher->getParam( 'aid', 'int' );
		if( !$iApplicantID )
		{
			return $this->getRet( null, RetCodeEnums::ERR_RES_LOCK_RESID_MSG, RetCodeEnums::ERR_RES_LOCK_RESID );
		}
		
		$iRet = $this->_dLock->unlockRes( $strLockName, $iResID, $iApplicantID );
		
		switch( $iRet )
		{
			case DLock::ERR_SUCCESS:
				return $this->getRet( null, RetCodeEnums::ERR_SUCCESS_MSG, RetCodeEnums::ERR_SUCCESS );
			case DLock::ERR_PARAMETERS:
				return $this->getRet( null, RetCodeEnums::ERR_PARAMS_MSG, RetCodeEnums::ERR_PARAMS );
			default:
				return $this->getRet( null, RetCodeEnums::ERR_OTHERS_MSG. RetCodeEnums::ERR_OTHERS );
		}
		
	}
	
}